---
title: Testing
---

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import CodeBlock from "@theme/CodeBlock";
import testingOriginalTestFlutter from "!!raw-loader!/docs/cookbooks/testing_original_test_flutter.dart";
import testingOriginalTestDart from "!!raw-loader!/docs/cookbooks/testing_original_test_dart.dart";
import repositorySnippet from "!!raw-loader!/docs/cookbooks/testing_repository.dart";
import testFlutter from "!!raw-loader!/docs/cookbooks/testing_flutter.dart";
import testDart from "!!raw-loader!/docs/cookbooks/testing_dart.dart";
import testFull from "!!raw-loader!/docs/cookbooks/testing_full.dart";
import testOverrideInfo from "!!raw-loader!/docs/cookbooks/testing_override_info.dart";
import { trimSnippet } from "../../src/components/CodeSnippet";

For any medium to large-scale applications, it is critical to test the application.

To successfully test our application, we will want the following things:

- No state should be preserved between `test`/`testWidgets`.  
  That means no global state in the application, or all global states should reset after each test.

- Being able to force our providers to have a specific state, either through
  mocking or by manipulating them until we reach the desired state.

Let's see one by one how [Riverpod] helps you with these.

## No state should be preserved between `test`/`testWidgets`.

Since providers are usually declared as global variables, you might worry about
that one.  
After all, global state makes testing very difficult, because it can require
lengthy `setUp`/`tearDown`.

But the reality is: While providers are declared as globals, the state of a provider
is **not** global.

Instead, it is stored in an object named [ProviderContainer], which you may have
seen if you looked at the dart-only examples.  
If you haven't, know that this [ProviderContainer] object is implicitly created
by [ProviderScope], the widget that enables [Riverpod] on our project.

Concretely what this means is, two `testWidgets` using providers do not share
any state.  
As such, there is no need for any `setUp`/`tearDown` at all.

But an example is better than lengthy explanations:

<Tabs
  defaultValue="testWidgets"
  values={[
    { label: 'testWidgets (Flutter)', value: 'testWidgets', },
    { label: 'test (Dart only)', value: 'test', },
  ]}
>
<TabItem value="testWidgets">

<CodeBlock>{trimSnippet(testingOriginalTestFlutter)}</CodeBlock>

</TabItem>
<TabItem value="test">

<CodeBlock>{trimSnippet(testingOriginalTestDart)}</CodeBlock>

</TabItem>
</Tabs>

As you can see, while `counterProvider` was declared as a global, no state was
shared between tests.  
As such, we do not have to worry about our tests potentially behaving differently
if executed in a different order, since they are running in complete isolation.

## Overriding the behavior of a provider during tests.

A common real-world application may have the following objects:

- It will have a `Repository` class, which provides a type-safe and simple API
  to perform HTTP requests.

- An object that manages the application state, and may use `Repository` to perform
  HTTP requests based on different factors.
  This may be a `ChangeNotifier`, `Bloc`, or even a provider.

Using [Riverpod], this may be represented as follows:

<CodeBlock>{trimSnippet(repositorySnippet)}</CodeBlock>

In this situation, when making a unit/widget test, we will typically want to
replace our `Repository` instance with a fake implementation that returns
a pre-defined response instead of making a real HTTP request.

We will then want our `todoListProvider` or equivalent to use the mocked implementation
of `Repository`.

To achieve this, we can use the `overrides` parameter of [ProviderScope]/[ProviderContainer]
to override the behavior of `repositoryProvider`:

<Tabs
  defaultValue="ProviderScope"
  values={[
    { label: 'ProviderScope (Flutter)', value: 'ProviderScope', },
    { label: 'ProviderContainer (Dart only)', value: 'ProviderContainer', },
  ]}
>
<TabItem value="ProviderScope">

<CodeBlock>{trimSnippet(testFlutter)}</CodeBlock>

</TabItem>
<TabItem value="ProviderContainer">

<CodeBlock>{trimSnippet(testDart)}</CodeBlock>

</TabItem>
</Tabs>

As you can see by the highlighted code, [ProviderScope]/[ProviderContainer]
allows replacing the implementation of a provider with a different behavior.

:::info
Some providers expose simplified ways to override their behavior.  
For example, [FutureProvider] allows overriding the provider with an `AsyncValue`:

<CodeBlock>{trimSnippet(testOverrideInfo)}</CodeBlock>

**Note**: As part of the 2.0.0 release, `overrideWithValue` methods are temporarily
removed. They will be added back in later versions.

:::

:::info
The syntax for overriding a provider with the `family` modifier is slightly different.

If you used a provider like this:

```dart
final response = ref.watch(myProvider('12345'));
```

You could override the provider as:

```dart
myProvider('12345').overrideWithValue(...));
```

:::

## Full widget test example

Wrapping up, here is the entire full code for our Flutter test.

<CodeBlock>{trimSnippet(testFull)}</CodeBlock>

[riverpod]: https://github.com/rrousselgit/riverpod
[providerscope]: https://pub.dev/documentation/flutter_riverpod/latest/flutter_riverpod/ProviderScope-class.html
[providercontainer]: https://pub.dev/documentation/riverpod/latest/riverpod/ProviderContainer-class.html
[futureprovider]: ../providers/future_provider
[zone]: https://api.flutter.dev/flutter/dart-async/Zone-class.html
